home *** CD-ROM | disk | FTP | other *** search
- Subject: v19i090: Cnews production release, Part13/19
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: utzoo!henry
- Posting-number: Volume 19, Issue 90
- Archive-name: cnews2/part13
-
- : ---CUT HERE---
- echo 'nntpdiffs/src/misc.c':
- sed 's/^X//' >'nntpdiffs/src/misc.c' <<'!'
- X#ifndef lint
- Xstatic char *sccsid = "@(#)misc.c 1.25 (Berkeley) 2/6/88";
- X#endif
- X
- X#include "../common/conf.h"
- X
- X#include "common.h"
- X
- X/*
- X * open_valid_art -- determine if a given article name is valid;
- X * if it is, return a file pointer to the open article,
- X * along with a unique id of the article.
- X *
- X * Parameters: "artname" is a string containing the
- X * name of the article.
- X * "id" is space for us to put the article
- X * id in.
- X *
- X * Returns: File pointer to the open article if the
- X * article is valid; NULL otherwise
- X *
- X * Side effects: None.
- X */
- X
- XFILE *
- Xopen_valid_art(artname, id)
- X char *artname;
- X char *id;
- X{
- X static int crnt_art_num;
- X static char crnt_art_id[MAXBUFLEN];
- X int fd;
- X struct stat statbuf;
- X
- X if (art_fp != NULL) {
- X if (crnt_art_num == atoi(artname)) {
- X if (fseek(art_fp, (long) 0, 0) < 0)
- X close_crnt();
- X else {
- X (void) strcpy(id, crnt_art_id);
- X return (art_fp);
- X }
- X } else
- X close_crnt();
- X }
- X
- X art_fp = fopen(artname, "r");
- X
- X if (art_fp == NULL)
- X return (NULL);
- X
- X fd = fileno(art_fp);
- X
- X if (fstat(fd, &statbuf) < 0) {
- X close_crnt();
- X return (NULL);
- X }
- X
- X if ((statbuf.st_mode & S_IFREG) != S_IFREG) {
- X close_crnt();
- X return (NULL);
- X }
- X
- X get_id(art_fp, id);
- X (void) strcpy(crnt_art_id, id);
- X crnt_art_num = atoi(artname);
- X return (art_fp);
- X}
- X
- X
- X/*
- X * gethistent -- return the path name of an article if it's
- X * in the history file.
- X *
- X * Parameters: "msg_id" is the message ID of the
- X * article, enclosed in <>'s.
- X *
- X * Returns: A char pointer to a static data area
- X * containing the full pathname of the
- X * article, or NULL if the message-id is not
- X * in thef history file.
- X *
- X * Side effects: opens dbm database
- X * (only once, keeps it open after that).
- X */
- X
- X#ifndef NDBM
- X# ifndef DBM
- X# ifndef USGHIST
- X# define USGHIST
- X# endif not USGHIST
- X# endif not DBM
- X#endif not DBM
- X
- Xchar *
- Xgethistent(msg_id)
- X char *msg_id;
- X{
- X char line[MAXBUFLEN];
- X char *tmp;
- X register char *cp;
- X long ltmp;
- X static char path[MAXPATHLEN];
- X#ifdef USGHIST
- X char *histfile();
- X register int len;
- X#else not USGHIST
- X#ifdef DBM
- X static int dbopen = 0;
- X datum fetch();
- X#else not DBM
- X static DBM *db = NULL; /* History file, dbm version */
- X#endif DBM
- X datum key, content;
- X#endif USGHIST
- X static FILE *hfp = NULL; /* history file, text version */
- X
- X#ifdef USGHIST
- X hfp = fopen(histfile(msg_id), "r");
- X if (hfp == NULL) {
- X#ifdef SYSLOG
- X syslog(LOG_ERR, "gethistent: histfile: %m");
- X#endif SYSLOG
- X return (NULL);
- X }
- X
- X len = strlen(msg_id);
- X while (fgets(line, sizeof (line), hfp))
- X if (!strncasecmp(msg_id, line, len))
- X break;
- X
- X if (feof(hfp)) {
- X (void) fclose(hfp);
- X return (NULL);
- X }
- X#else not USGHIST
- X#ifdef DBM
- X if (!dbopen) {
- X if (dbminit(historyfile) < 0) {
- X#ifdef SYSLOG
- X syslog(LOG_ERR, "openartbyid: dbminit %s: %m",
- X historyfile);
- X#endif SYSLOG
- X return (NULL);
- X } else
- X dbopen = 1;
- X }
- X#else /* ndbm */
- X if (db == NULL) {
- X db = dbm_open(historyfile, O_RDONLY, 0);
- X if (db == NULL) {
- X#ifdef SYSLOG
- X syslog(LOG_ERR, "openartbyid: dbm_open %s: %m",
- X historyfile);
- X#endif SYSLOG
- X return (NULL);
- X }
- X }
- X#endif DBM
- X
- X key.dptr = msg_id;
- X key.dsize = strlen(msg_id) + 1;
- X
- X#ifdef DBM
- X content = fetch(key);
- X#else /* ndbm */
- X content = dbm_fetch(db, key);
- X#endif DBM
- X if (content.dptr == NULL)
- X return (NULL);
- X
- X if (hfp == NULL) {
- X hfp = fopen(historyfile, "r");
- X if (hfp == NULL) {
- X#ifdef SYSLOG
- X syslog(LOG_ERR, "message: fopen %s: %m",
- X historyfile);
- X#endif SYSLOG
- X return (NULL);
- X }
- X }
- X
- X bcopy(content.dptr, (char *)<mp, sizeof (long));
- X if (fseek(hfp, ltmp, 0) < 0) {
- X#ifdef SYSLOG
- X syslog(LOG_ERR, "message: fseek: %m");
- X#endif SYSLOG
- X return (NULL);
- X }
- X
- X (void) fgets(line, sizeof(line), hfp);
- X#endif USGHIST
- X
- X if ((cp = index(line, '\n')) != NULL)
- X *cp = '\0';
- X cp = index(line, '\t');
- X if (cp != NULL)
- X cp = index(cp+1, '\t');
- X if (cp == NULL) {
- X#ifdef SYSLOG
- X syslog(LOG_ERR,
- X "message: malformed line in history file at %ld bytes, id %s",
- X ltmp, msg_id);
- X#endif SYSLOG
- X return (NULL);
- X }
- X tmp = cp+1;
- X
- X if ((cp = index(tmp, ' ')) != NULL)
- X *cp = '\0';
- X
- X while ((cp = index(tmp, '.')) != NULL)
- X *cp = '/';
- X
- X (void) strcpy(path, spooldir);
- X (void) strcat(path, "/");
- X (void) strcat(path, tmp);
- X
- X return (path);
- X}
- X
- X/*
- X * openartbyid -- open an article by message-id.
- X *
- X * Arguments: "msg_id" is the message-id of the article
- X * to open.
- X *
- X * Returns: File pointer to opened article, or NULL if
- X * the article was not in the history file or
- X * could not be opened.
- X *
- X * Side effects: Opens article.
- X */
- X
- XFILE *
- Xopenartbyid(msg_id)
- X char *msg_id;
- X{
- X char *path;
- X
- X path = gethistent(msg_id);
- X if (path != NULL)
- X return (fopen(path, "r"));
- X else
- X return (NULL);
- X}
- X
- X
- X/*
- X * check_ngperm -- check to see if they're allowed to see this
- X * article by matching Newsgroups: and Distribution: line.
- X *
- X * Parameters: "fp" is the file pointer of this article.
- X *
- X * Returns: 0 if they're not allowed to see it.
- X * 1 if they are.
- X *
- X * Side effects: None.
- X */
- X
- Xcheck_ngperm(fp)
- X register FILE *fp;
- X{
- X char buf[MAXBUFLEN];
- X register char *cp;
- X static char **ngarray;
- X int ngcount;
- X
- X if (ngpermcount == 0)
- X return (1);
- X
- X while (fgets(buf, sizeof (buf), fp) != NULL) {
- X if (buf[0] == '\n') /* End of header */
- X break;
- X if (buf[0] != 'N' && buf[0] != 'n')
- X continue;
- X cp = index(buf, '\n');
- X if (cp)
- X *cp = '\0';
- X cp = index(buf, ':');
- X if (cp == NULL)
- X continue;
- X *cp = '\0';
- X if (!strcasecmp(buf, "newsgroups")) {
- X ngcount = get_nglist(&ngarray, cp+2);
- X break;
- X }
- X }
- X
- X (void) rewind(fp);
- X
- X if (ngcount == 0) /* Either no newgroups or null entry */
- X return (1);
- X
- X return (ngmatch(s1strneql, ALLBUT,
- X ngpermlist, ngpermcount, ngarray, ngcount));
- X}
- X
- X
- X/*
- X * spew -- spew out the contents of a file to stdout, doing
- X * the necessary cr-lf additions at the end. Finish with
- X * a "." on a line by itself, and an fflush(stdout).
- X *
- X * Parameters: "how" tells what part of the file we
- X * want spewed:
- X * ARTICLE The entire thing.
- X * HEAD Just the first part.
- X * BODY Just the second part.
- X * "fp" is the open file to spew from.
- X *
- X * Returns: Nothing.
- X *
- X * Side effects: Changes current position in file.
- X */
- X
- Xspew(fp, how)
- X FILE *fp;
- X int how;
- X{
- X char line[NNTP_STRLEN];
- X register char *cp;
- X
- X#ifdef LOG
- X ++arts_acsd;
- X#endif
- X
- X if (how == STAT) {
- X (void) fflush(stdout);
- X return;
- X }
- X
- X while (fgets(line, sizeof(line)-6, fp) != NULL && *line != '\n') {
- X if (how == BODY) /* We need to skip this anyway */
- X continue;
- X cp = index(line, '\n');
- X if (cp != NULL)
- X *cp = '\0';
- X if (*line == '.')
- X putchar('.');
- X putline(line);
- X if (cp == NULL) {
- X for (;;) {
- X if ((fgets(line, sizeof(line)-6, fp) == NULL)
- X || (index(line, '\n') != NULL))
- X break;
- X }
- X }
- X }
- X
- X if (how == HEAD) {
- X putchar('.');
- X putchar('\r');
- X putchar('\n');
- X (void) fflush(stdout);
- X return;
- X } else if (how == ARTICLE) {
- X putchar('\r');
- X putchar('\n');
- X }
- X
- X while (fgets(line, sizeof(line)-6, fp) != NULL) {
- X cp = index(line, '\n');
- X if (cp != NULL)
- X *cp = '\0';
- X if (*line == '.')
- X putchar('.');
- X putline(line);
- X
- X if (cp == NULL) {
- X for (;;) {
- X if ((fgets(line, sizeof(line)-6, fp) == NULL)
- X || (index(line, '\n') != NULL))
- X break;
- X }
- X }
- X }
- X putchar('.');
- X putchar('\r');
- X putchar('\n');
- X (void) fflush(stdout);
- X}
- X
- X
- X/*
- X * get_id -- get the message id of the current article.
- X *
- X * Parameters: "art_fp" is a pointer to the open file.
- X * "id" is space for the message ID.
- X *
- X * Returns: Nothing.
- X *
- X * Side effects: Seeks and rewinds on "art_fp".
- X * Changes space pointed to by "id".
- X */
- X
- Xget_id(art_fp, id)
- X register FILE *art_fp;
- X char *id;
- X{
- X char line[MAXBUFLEN];
- X register char *cp;
- X
- X while (fgets(line, sizeof(line), art_fp) != NULL) {
- X if (*line == '\n')
- X break;
- X if (*line == 'M' || *line == 'm') { /* "Message-ID" */
- X if ((cp = index(line, ' ')) != NULL) {
- X *cp = '\0';
- X if (!strcasecmp(line, "Message-ID:")) {
- X (void) strcpy(id, cp + 1);
- X if ((cp = index(id, '\n')) != NULL)
- X *cp = '\0';
- X (void) rewind(art_fp);
- X return;
- X }
- X }
- X }
- X }
- X (void) rewind(art_fp);
- X (void) strcpy(id, "<0>");
- X}
- X
- X
- X/*
- X * close_crnt -- close the current article file pointer, if it's
- X * open.
- X *
- X * Parameters: None.
- X *
- X * Returns: Nothing.
- X *
- X * Side effects: Closes "art_fp" if it's open; sets "art_fp" to NULL.
- X */
- X
- Xclose_crnt()
- X{
- X if (art_fp != NULL)
- X (void) fclose(art_fp);
- X art_fp = NULL;
- X}
- X
- X
- X/*
- X * findart -- find an article number in the article array.
- X *
- X * Parameters: "artname" is a string containing
- X * the name of the article.
- X *
- X * Returns: An index into "art_array",
- X * or -1 if "artname" isn't in "art_array".
- X *
- X * Side effects: None.
- X *
- X * Improvement: Replace this linear search with a binary one.
- X */
- X
- Xfindart(artname)
- X char *artname;
- X{
- X register int i, artnum;
- X
- X artnum = atoi(artname);
- X
- X for (i = 0; i < num_arts; ++i)
- X if (art_array[i] == artnum)
- X return(i);
- X
- X return (-1);
- X}
- X
- X
- X/*
- X * get_distlist -- return a nicely set up array of distribution groups
- X * along with a count, when given an NNTP-spec distribution list
- X * in the form <dist1,dist2,...,distn>.
- X *
- X * Parameters: "array" is storage for our array,
- X * set to point at some static data.
- X * "list" is the NNTP distribution list.
- X *
- X * Returns: Number of distributions found.
- X * -1 on error.
- X *
- X * Side effects: Changes static data area.
- X */
- X
- Xget_distlist(array, list)
- X char ***array;
- X char *list;
- X{
- X char *cp;
- X int distcount;
- X static char **dist_list = (char **) NULL;
- X
- X if (list[0] != '<')
- X return (-1);
- X
- X cp = index(list + 1, '>');
- X if (cp != NULL)
- X *cp = '\0';
- X else
- X return (-1);
- X
- X for (cp = list + 1; *cp != '\0'; ++cp)
- X if (*cp == ',')
- X *cp = ' ';
- X distcount = parsit(list + 1, &dist_list);
- X *array = dist_list;
- X return (distcount);
- X}
- X
- X
- X/*
- X * lower -- convert a character to lower case, if it's upper case.
- X *
- X * Parameters: "c" is the character to be
- X * converted.
- X *
- X * Returns: "c" if the character is not
- X * upper case, otherwise the lower
- X * case eqivalent of "c".
- X *
- X * Side effects: None.
- X */
- X
- Xchar
- Xlower(c)
- X register char c;
- X{
- X if (isascii(c) && isupper(c))
- X c = c - 'A' + 'a';
- X return (c);
- X}
- X
- X
- X/* the following is from news 2.11 */
- X
- X#ifdef USG
- X/*
- X** Generate the appropriate history subfile name
- X*/
- Xchar *
- Xhistfile(hline)
- Xchar *hline;
- X{
- X char chr; /* least significant digit of article number */
- X static char subfile[BUFSIZ];
- X
- X chr = findhfdigit(hline);
- X sprintf(subfile, "%s.d/%c", HISTORY_FILE, chr);
- X return subfile;
- X}
- X
- Xfindhfdigit(fn)
- Xchar *fn;
- X{
- X register char *p;
- X register int chr;
- X
- X p = index(fn, '@');
- X if (p != NULL && p > fn)
- X chr = *(p - 1);
- X else
- X chr = '0';
- X if (!isdigit(chr))
- X chr = '0';
- X return chr;
- X}
- Xbcopy(s, d, l)
- X register char *s, *d;
- X register int l;
- X{
- X while (l-- > 0)
- X *d++ = *s++;
- X}
- X
- Xbcmp(s1, s2, l)
- X register char *s1, *s2;
- X register int l;
- X{
- X if (l == 0)
- X return (0);
- X
- X do
- X if (*s1++ != *s2++)
- X break;
- X while (--l);
- X
- X return (l);
- X}
- X
- Xbzero(p, l)
- X register char *p;
- X register int l;
- X{
- X while (l-- > 0)
- X *p++ = 0;
- X}
- X
- Xdup2(x,y)
- Xint x,y;
- X{
- X close(y);
- X return(fcntl(x, F_DUPFD,y ));
- X}
- X#endif USG
- !
- echo 'nntpdiffs/src/newnews.c':
- sed 's/^X//' >'nntpdiffs/src/newnews.c' <<'!'
- X#ifndef lint
- Xstatic char *sccsid = "@(#)newnews.c 1.19 (Berkeley) 2/6/88";
- X#endif
- X
- X#include "common.h"
- X#include "time.h"
- X
- X#ifdef LOG
- Xint nn_told = 0;
- Xint nn_took = 0;
- X#endif
- X
- X
- X/*
- X * NEWNEWS newsgroups date time ["GMT"] [<distributions>]
- X *
- X * Return the message-id's of any news articles past
- X * a certain date and time, within the specified distributions.
- X *
- X */
- X
- Xnewnews(argc, argv)
- X register int argc;
- X char *argv[];
- X{
- X register char *cp, *ngp;
- X char *key;
- X char datebuf[32];
- X char line[MAXBUFLEN];
- X char **distlist, **histlist;
- X static char **nglist;
- X int distcount, ngcount, histcount;
- X int all;
- X FILE *fp;
- X long date;
- X long dtol();
- X char *ltod();
- X#ifdef USG
- X FILE *tmplst;
- X int i;
- X char *tmpfile;
- X#endif USG
- X
- X if (argc < 4) {
- X printf("%d Usage: NEWNEWS newsgroups yymmdd hhmmss [\"GMT\"] [<distributions>].\r\n",
- X ERR_CMDSYN);
- X (void) fflush(stdout);
- X return;
- X }
- X
- X#ifdef LOG
- X sprintf(line, "%s newnews %s %s %s %s %s",
- X hostname,
- X argv[1],
- X argv[2],
- X argv[3],
- X (argc >= 5 && *argv[4] == 'G') ? "GMT" : "local",
- X (argc >= 5 && *argv[argc-1] == '<') ? argv[argc-1] : "none");
- X syslog(LOG_INFO, line);
- X#endif
- X
- X all = (argv[1][0] == '*' && argv[1][1] == '\0');
- X if (!all) {
- X ngcount = get_nglist(&nglist, argv[1]);
- X if (ngcount == 0) {
- X printf("%d Bogus newsgroup specifier: %s\r\n",
- X ERR_CMDSYN, argv[1]);
- X (void) fflush(stdout);
- X return;
- X }
- X }
- X
- X /* YYMMDD HHMMSS */
- X if (strlen(argv[2]) != 6 || strlen(argv[3]) != 6) {
- X printf("%d Date/time must be in form YYMMDD HHMMSS.\r\n",
- X ERR_CMDSYN);
- X (void) fflush(stdout);
- X return;
- X }
- X
- X (void) strcpy(datebuf, argv[2]);
- X (void) strcat(datebuf, argv[3]);
- X
- X argc -= 4;
- X argv += 4;
- X
- X /*
- X * Flame on. The history file is not stored in GMT, but
- X * in local time. So we have to convert GMT to local time
- X * if we're given GMT, otherwise we need only chop off the
- X * the seconds. Such braindamage.
- X */
- X
- X key = datebuf; /* Unless they specify GMT */
- X
- X if (argc > 0) {
- X if (!strcasecmp(*argv, "GMT")) { /* Which we handle here */
- X date = dtol(datebuf);
- X if (date < 0) {
- X printf("%d Invalid date specification.\r\n",
- X ERR_CMDSYN);
- X (void) fflush(stdout);
- X return;
- X }
- X date = gmt_to_local(date);
- X key = ltod(date);
- X ++argv;
- X --argc;
- X }
- X }
- X
- X /* So, key now points to the local time, but we need to zap secs */
- X
- X key[10] = '\0';
- X
- X distcount = 0;
- X if (argc > 0) {
- X distcount = get_distlist(&distlist, *argv);
- X if (distcount < 0) {
- X printf("%d Bad distribution list: %s\r\n", ERR_CMDSYN,
- X *argv);
- X (void) fflush(stdout);
- X return;
- X }
- X }
- X
- X#ifdef USG
- X if ((tmpfile = mktemp("/tmp/listXXXXXX")) == NULL ||
- X (tmplst = fopen(tmpfile, "w+")) == NULL) {
- X printf("%d Cannot process history file.\r\n", ERR_FAULT);
- X (void) fflush(stdout);
- X return;
- X }
- X
- X for (i = 0; i < 9; i++) {
- X sprintf(historyfile, "%s.d/%d", HISTORY_FILE, i);
- X#endif USG
- X
- X fp = fopen(historyfile, "r");
- X if (fp == NULL) {
- X#ifdef SYSLOG
- X syslog(LOG_ERR, "newnews: fopen %s: %m", historyfile);
- X#endif
- X#ifndef USG
- X printf("%d Cannot open history file.\r\n", ERR_FAULT);
- X (void) fflush(stdout);
- X return;
- X#else USG
- X continue;
- X#endif USG
- X }
- X
- X#ifndef USG
- X printf("%d New news by message id follows.\r\n", OK_NEWNEWS);
- X#endif not USG
- X
- X if (seekuntil(fp, key, line, sizeof (line)) < 0) {
- X#ifndef USG
- X printf(".\r\n");
- X (void) fflush(stdout);
- X#endif not USG
- X (void) fclose(fp);
- X#ifndef USG
- X return;
- X#else USG
- X continue;
- X#endif USG
- X }
- X
- X/*
- X * History file looks like:
- X *
- X * <1569@emory.UUCP> 01/22/86 09:19 net.micro.att/899 ucb.general/2545
- X * ^--tab ^--tab ^--space ^sp\0
- X * Sometimes the newsgroups are missing; we try to be robust and
- X * ignore such bogosity. We tackle this by our usual parse routine,
- X * and break the list of articles in the history file into an argv
- X * array with one newsgroup per entry.
- X */
- X
- X do {
- X if ((cp = index(line, '\t')) == NULL)
- X continue;
- X
- X if ((ngp = index(cp+1, '\t')) == NULL) /* 2nd tab */
- X continue;
- X ++ngp; /* Points at newsgroup list */
- X if (*ngp == '\n')
- X continue;
- X histcount = get_histlist(&histlist, ngp);
- X if (histcount == 0)
- X continue;
- X
- X /*
- X * For each newsgroup on this line in the history
- X * file, check it against the newsgroup names we're given.
- X * If it matches, then see if we're hacking distributions.
- X * If so, open the file and match the distribution line.
- X */
- X
- X if (!all)
- X if (!ngmatch(restreql, 0, nglist, ngcount,
- X histlist, histcount))
- X continue;
- X
- X if (distcount)
- X if (!distmatch(distlist, distcount, histlist, histcount))
- X continue;
- X
- X *cp = '\0';
- X#ifdef USG
- X fputs(line, tmplst);
- X fputc('\n', tmplst);
- X#else not USG
- X putline(line);
- X#endif not USG
- X#ifdef LOG
- X nn_told++;
- X#endif
- X } while (fgets(line, sizeof(line), fp) != NULL);
- X
- X#ifndef USG
- X putchar('.');
- X putchar('\r');
- X putchar('\n');
- X (void) fflush(stdout);
- X#endif
- X (void) fclose(fp);
- X#ifdef USG
- X }
- X printf("%d New news by message id follows.\r\n", OK_NEWNEWS);
- X rewind(tmplst);
- X while (fgets(line, sizeof(line), tmplst) != NULL)
- X putline(line);
- X putchar('.');
- X putchar('\r');
- X putchar('\n');
- X (void) fflush(stdout);
- X (void) fclose(tmplst);
- X (void) unlink(tmpfile);
- X#endif USG
- X}
- X
- X
- X/*
- X * seekuntil -- seek through the history file looking for
- X * a line with date "key". Get that line, and return.
- X *
- X * Parameters: "fp" is the active file.
- X * "key" is the date, in form YYMMDDHHMM (no SS)
- X * "line" is storage for the first line we find.
- X *
- X * Returns: -1 on error, 0 otherwise.
- X *
- X * Side effects: Seeks in history file, modifies line.
- X */
- X
- Xseekuntil(fp, akey, line, linesize)
- X FILE *fp;
- X char *akey;
- X char *line;
- X int linesize;
- X{
- X char datetime[32];
- X register int c;
- X register long top, bot, mid;
- X extern long dtol();
- X char key[30];
- X
- X (void) sprintf(key, "%ld", dtol(akey)); /* akey -> time_t in ascii */
- X bot = 0;
- X (void) fseek(fp, 0L, 2);
- X top = ftell(fp);
- X for(;;) {
- X mid = (top+bot)/2;
- X (void) fseek(fp, mid, 0);
- X do {
- X c = getc(fp);
- X mid++;
- X } while (c != EOF && c!='\n');
- X if (!getword(fp, datetime, line, linesize)) {
- X return (-1);
- X }
- X switch (compare(key, datetime)) {
- X case -2:
- X case -1:
- X case 0:
- X if (top <= mid)
- X break;
- X top = mid;
- X continue;
- X case 1:
- X case 2:
- X bot = mid;
- X continue;
- X }
- X break;
- X }
- X (void) fseek(fp, bot, 0);
- X while(ftell(fp) < top) {
- X if (!getword(fp, datetime, line, linesize)) {
- X return (-1);
- X }
- X switch(compare(key, datetime)) {
- X case -2:
- X case -1:
- X case 0:
- X break;
- X case 1:
- X case 2:
- X continue;
- X }
- X break;
- X }
- X
- X return (0);
- X}
- X
- X
- Xcompare(s, t)
- X register char *s, *t;
- X{
- X for (; *s == *t; s++, t++)
- X if (*s == 0)
- X return(0);
- X return (*s == 0 ? -1:
- X *t == 0 ? 1:
- X *s < *t ? -2:
- X 2);
- X}
- X
- X
- X/*
- X * C news version of getword.
- X */
- Xgetword(fp, w, line, linesize)
- X FILE *fp;
- X register char *w;
- X char *line;
- X int linesize;
- X{
- X register char *cp;
- X extern char *index();
- X
- X if (fgets(line, linesize, fp) == NULL)
- X return (0);
- X w[0] = '\0'; /* in case of bad format */
- X if (cp = index(line, '\t')) { /* find 2nd field */
- X register char *endp;
- X
- X *cp++ = '\0';
- X endp = index(cp, '~'); /* end of date-received */
- X if (endp == NULL)
- X endp = index(cp, '\t'); /* end of expiry */
- X if (endp != NULL) {
- X (void) strncpy(w, cp, endp - cp);
- X w[endp - cp] = '\0';
- X }
- X }
- X return (1);
- X}
- X
- X
- X/*
- X * distmatch -- see if a file matches a set of distributions.
- X * We have to do this by (yech!) opening the file, finding
- X * the Distribution: line, if it has one, and seeing if the
- X * things match.
- X *
- X * Parameters: "distlist" is the distribution list
- X * we want.
- X * "distcount" is the count of distributions in it.
- X * "grouplist" is the list of groups (articles)
- X * for this line of the history file. Note that
- X * this isn't quite a filename.
- X * "groupcount" is the count of groups in it.
- X *
- X * Returns: 1 if the article is in the given distribution.
- X * 0 otherwise.
- X */
- X
- Xdistmatch(distlist, distcount, grouplist, groupcount)
- X char *distlist[];
- X int distcount;
- X char *grouplist[];
- X int groupcount;
- X{
- X register char c;
- X register char *cp;
- X register FILE *fp;
- X register int i, j;
- X char buf[MAXBUFLEN];
- X
- X (void) strcpy(buf, spooldir);
- X (void) strcat(buf, "/");
- X (void) strcat(buf, grouplist[0]);
- X
- X for (cp = buf; *cp; cp++)
- X if (*cp == '.')
- X *cp = '/';
- X
- X fp = fopen(buf, "r");
- X if (fp == NULL) {
- X#ifdef SYSLOG
- X syslog(LOG_ERR, "distmatch: fopen %s: %m", buf);
- X#endif
- X return (0);
- X }
- X
- X while (fgets(buf, sizeof (buf), fp) != NULL) {
- X if ((c = buf[0]) == '\n') /* End of header */
- X break;
- X if (c != 'd' && c != 'D')
- X continue;
- X cp = index(cp + 1, '\n');
- X if (cp)
- X *cp = '\0';
- X cp = index(buf, ':');
- X if (cp == NULL)
- X continue;
- X *cp = '\0';
- X if (!strcasecmp(buf, "distribution")) {
- X for (i = 0; i < distcount; ++i) {
- X if (!strcasecmp(cp + 2, distlist[i])) {
- X (void) fclose(fp);
- X return (1);
- X }
- X }
- X (void) fclose(fp);
- X return (0);
- X }
- X }
- X
- X (void) fclose(fp);
- X
- X /*
- X * We've finished the header with no distribution field.
- X * So we'll assume that the distribution is the characters
- X * up to the first dot in the newsgroup name.
- X */
- X
- X for (i = 0; i < groupcount; i++) {
- X cp = index(grouplist[i], '.');
- X if (cp)
- X *cp = '\0';
- X for (j = 0; j < distcount; j++)
- X if (!strcasecmp(grouplist[i], distlist[j]))
- X return (1);
- X }
- X
- X return (0);
- X}
- X
- X
- X/*
- X * get_histlist -- return a nicely set up array of newsgroups
- X * (actually, net.foo.bar/article_num) along with a count.
- X *
- X * Parameters: "array" is storage for our array,
- X * set to point at some static data.
- X * "list" is the history file newsgroup list.
- X *
- X * Returns: Number of group specs found.
- X *
- X * Side effects: Changes static data area.
- X */
- X
- Xget_histlist(array, list)
- X char ***array;
- X char *list;
- X{
- X register int histcount;
- X register char *cp;
- X static char **hist_list = (char **) NULL;
- X
- X cp = index(list, '\n');
- X if (cp)
- X *cp-- = '\0';
- X histcount = parsit(list, &hist_list);
- X *array = hist_list;
- X return (histcount);
- X}
- X
- X
- X/*
- X * get_nglist -- return a nicely set up array of newsgroups
- X * along with a count, when given an NNTP-spec newsgroup list
- X * in the form ng1,ng2,ng...
- X *
- X * Parameters: "array" is storage for our array,
- X * set to point at some static data.
- X * "list" is the NNTP newsgroup list.
- X *
- X * Returns: Number of group specs found.
- X *
- X * Side effects: Changes static data area.
- X */
- X
- Xget_nglist(array, list)
- X char ***array;
- X char *list;
- X{
- X register char *cp;
- X register int ngcount;
- X
- X for (cp = list; *cp != '\0'; ++cp)
- X if (*cp == ',')
- X *cp = ' ';
- X
- X ngcount = parsit(list, array);
- X
- X return (ngcount);
- X}
- !
- echo 'nntpdiffs/src/serve.c':
- sed 's/^X//' >'nntpdiffs/src/serve.c' <<'!'
- X#ifndef lint
- Xstatic char *sccsid = "@(#)serve.c 1.29 (Berkeley) 2/6/88";
- X#endif
- X
- X/*
- X * Main server routine
- X */
- X
- X#include "common.h"
- X#include <signal.h>
- X#ifdef USG
- X#include <sys/times.h>
- X#else
- X#include <sys/time.h>
- X#endif
- X
- X#ifdef LOG
- X# ifndef USG
- X# include <sys/resource.h>
- X# endif not USG
- X#endif
- X
- Xextern int ahbs(), group(), help(), ihave();
- Xextern int list(), newgroups(), newnews(), nextlast(), post();
- Xextern int slave(), stat(), xhdr();
- X
- Xstatic struct cmdent {
- X char *cmd_name;
- X int (*cmd_fctn)();
- X} cmdtbl[] = {
- X "article", ahbs,
- X "body", ahbs,
- X "group", group,
- X "head", ahbs,
- X "help", help,
- X "ihave", ihave,
- X "last", nextlast,
- X "list", list,
- X "newgroups", newgroups,
- X "newnews", newnews,
- X "next", nextlast,
- X "post", post,
- X "slave", slave,
- X "stat", ahbs,
- X#ifdef XHDR
- X "xhdr", xhdr,
- X#endif XHDR
- X};
- X#define NUMCMDS (sizeof(cmdtbl) / sizeof(struct cmdent))
- X
- X
- X/*
- X * serve -- given a connection on stdin/stdout, serve
- X * a client, executing commands until the client
- X * says goodbye.
- X *
- X * Parameters: None.
- X *
- X * Returns: Exits.
- X *
- X * Side effects: Talks to client, does a lot of
- X * stuff.
- X */
- X
- Xserve()
- X{
- X char line[NNTP_STRLEN];
- X char host[MAXHOSTNAMELEN];
- X char gdbuf[MAXBUFLEN];
- X char **argp;
- X char *timeptr, *cp;
- X int argnum, i;
- X double Tstart, Tfinish;
- X double user, sys;
- X#ifdef USG
- X time_t start, finish;
- X#else not USG
- X struct timeval start, finish;
- X#endif not USG
- X extern char *ctime();
- X#ifdef POSTER
- X struct passwd *pp;
- X#endif
- X#ifdef LOG
- X# ifdef USG
- X struct tms cpu;
- X# else not USG
- X struct rusage me, kids;
- X# endif not USG
- X# ifdef TIMEOUT
- X void timeout();
- X# endif
- X
- X grps_acsd = arts_acsd = 0;
- X#endif
- X
- X /* Not all systems pass fd's 1 and 2 from inetd */
- X
- X (void) close(1);
- X (void) close(2);
- X (void) dup(0);
- X (void) dup(0);
- X
- X /* If we're ALONE, then we've already opened syslog */
- X
- X#ifndef ALONE
- X# ifdef SYSLOG
- X# ifdef BSD_42
- X openlog("nntpd", LOG_PID);
- X# else
- X openlog("nntpd", LOG_PID, SYSLOG);
- X# endif
- X# endif
- X#endif
- X
- X#ifdef ALONE
- X#ifndef USG
- X (void) signal(SIGCHLD, SIG_IGN);
- X#endif not USG
- X#endif
- X
- X /* Ignore SIGPIPE, since we'll see closed connections with read */
- X
- X (void) signal(SIGPIPE, SIG_IGN);
- X
- X /* Get permissions and see if we can talk to this client */
- X
- X host_access(&canread, &canpost, &canxfer, gdbuf);
- X
- X if (gethostname(host, sizeof(host)) < 0)
- X (void) strcpy(host, "Amnesiac");
- X
- X if (!canread && !canxfer) {
- X printf("%d %s NNTP server can't talk to you. Goodbye.\r\n",
- X ERR_ACCESS, host);
- X (void) fflush(stdout);
- X#ifdef LOG
- X syslog(LOG_INFO, "%s refused connection", hostname);
- X#endif
- X exit(1);
- X }
- X
- X /* If we can talk, proceed with initialization */
- X
- X ngpermcount = get_nglist(&ngpermlist, gdbuf);
- X
- X#ifdef POSTER
- X pp = getpwnam(POSTER);
- X if (pp != NULL) {
- X uid_poster = pp->pw_uid;
- X gid_poster = pp->pw_gid;
- X } else
- X#endif
- X uid_poster = gid_poster = 0;
- X
- X#ifndef FASTFORK
- X num_groups = 0;
- X num_groups = read_groups(); /* Read in the active file */
- X#else
- X signal(SIGALRM, SIG_IGN); /* Children don't deal with */
- X /* these things */
- X#endif
- X
- X art_fp = NULL;
- X argp = (char **) NULL; /* for first time */
- X
- X#ifdef USG
- X (void) time(&start);
- X Tstart = (double) start;
- X timeptr = ctime(&start);
- X#else not USG
- X (void) gettimeofday(&start, (struct timezone *)NULL);
- X Tstart = (double) start.tv_sec - ((double)start.tv_usec)/1000000.0;
- X timeptr = ctime(&start.tv_sec);
- X#endif not USG
- X if ((cp = index(timeptr, '\n')) != NULL)
- X *cp = '\0';
- X else
- X timeptr = "Unknown date";
- X
- X printf("%d %s NNTP server version %s ready at %s (%s).\r\n",
- X canpost ? OK_CANPOST : OK_NOPOST,
- X host, nntp_version,
- X timeptr,
- X canpost ? "posting ok" : "no posting");
- X (void) fflush(stdout);
- X
- X /*
- X * Now get commands one at a time and execute the
- X * appropriate routine to deal with them.
- X */
- X
- X#ifdef TIMEOUT
- X (void) signal(SIGALRM, timeout);
- X (void) alarm(TIMEOUT);
- X#endif TIMEOUT
- X
- X while (fgets(line, sizeof(line), stdin) != NULL) {
- X#ifdef TIMEOUT
- X (void) alarm(0);
- X#endif TIMEOUT
- X
- X cp = index(line, '\r'); /* Zap CR-LF */
- X if (cp != NULL)
- X *cp = '\0';
- X else {
- X cp = index(line, '\n');
- X if (cp != NULL)
- X *cp = '\0';
- X }
- X
- X if ((argnum = parsit(line, &argp)) == 0)
- X continue; /* Null command */
- X else {
- X for (i = 0; i < NUMCMDS; ++i)
- X if (!strcasecmp(cmdtbl[i].cmd_name, argp[0]))
- X break;
- X if (i < NUMCMDS)
- X (*cmdtbl[i].cmd_fctn)(argnum, argp);
- X else {
- X if (!strcasecmp(argp[0], "quit"))
- X break;
- X#ifdef LOG
- X syslog(LOG_INFO, "%s unrecognized %s",
- X hostname,
- X line);
- X#endif
- X printf("%d Command unrecognized.\r\n",
- X ERR_COMMAND);
- X (void) fflush(stdout);
- X }
- X }
- X#ifdef TIMEOUT
- X (void) alarm(TIMEOUT);
- X#endif TIMEOUT
- X }
- X
- X printf("%d %s closing connection. Goodbye.\r\n", OK_GOODBYE, host);
- X (void) fflush(stdout);
- X#ifndef UNBATCHED_INPUT
- X {
- X char errbuf[2 * NNTP_STRLEN];
- X
- X enqpartbatch(CONT_XFER, ERR_XFERFAIL, errbuf);
- X }
- X#endif
- X
- X
- X#ifdef LOG
- X if (ferror(stdout))
- X syslog(LOG_ERR, "%s disconnect: %m", hostname);
- X
- X#ifdef USG
- X (void) time(&finish);
- X Tfinish = (double) finish;
- X
- X#ifndef HZ
- X#define HZ 60.0 /* typical system clock ticks - param.h */
- X#endif not HZ
- X
- X (void) times(&cpu);
- X user = (double)(cpu.tms_utime + cpu.tms_cutime) / HZ;
- X sys = (double)(cpu.tms_stime + cpu.tms_cstime) / HZ;
- X#else not USG
- X (void) gettimeofday(&finish, (struct timezone *)NULL);
- X Tfinish = (double) finish.tv_sec - ((double)finish.tv_usec)/1000000.0;
- X
- X (void) getrusage(RUSAGE_SELF, &me);
- X (void) getrusage(RUSAGE_CHILDREN, &kids);
- X
- X user = (double) me.ru_utime.tv_sec + me.ru_utime.tv_usec/1000000.0 +
- X kids.ru_utime.tv_sec + kids.ru_utime.tv_usec/1000000.0;
- X sys = (double) me.ru_stime.tv_sec + me.ru_stime.tv_usec/1000000.0 +
- X kids.ru_stime.tv_sec + kids.ru_stime.tv_usec/1000000.0;
- X#endif not USG
- X if (grps_acsd)
- X syslog(LOG_INFO, "%s exit %d articles %d groups",
- X hostname, arts_acsd, grps_acsd);
- X if (nn_told)
- X syslog(LOG_INFO, "%s newnews_stats told %d took %d",
- X hostname, nn_told, nn_took);
- X if (ih_accepted || ih_rejected || ih_failed)
- X syslog(LOG_INFO,
- X "%s ihave_stats accepted %d rejected %d failed %d",
- X hostname,
- X ih_accepted,
- X ih_rejected,
- X ih_failed);
- X (void) sprintf(line, "user %.1f system %.1f elapsed %.1f",
- X user, sys, Tfinish - Tstart);
- X syslog(LOG_INFO, "%s times %s", hostname, line);
- X#endif LOG
- X
- X#ifdef PROFILE
- X profile();
- X#endif
- X exit(0);
- X}
- X
- X
- X#ifdef TIMEOUT
- X/*
- X * No activity for TIMEOUT seconds, so print an error message
- X * and close the connection.
- X */
- X
- Xvoid
- Xtimeout()
- X{
- X printf("%d Timeout after %d seconds, closing connection.\r\n",
- X ERR_FAULT, TIMEOUT);
- X (void) fflush(stdout);
- X
- X#ifdef LOG
- X syslog(LOG_ERR, "%s timeout", hostname);
- X#endif LOG
- X
- X exit(1);
- X}
- X#endif TIMEOUT
- !
- echo 'nntpdiffs/src.allnew/batch.c':
- sed 's/^X//' >'nntpdiffs/src.allnew/batch.c' <<'!'
- X/*
- X * rnews - setuid-news fake rnews for nntp: appends article to a batch with
- X * a fixed name under in.coming. if batch is too big or old, rename
- X * batch to be an input candidate and kick off a newsrun to process
- X * the batch. the batch file is locked during appending.
- X * Cooperates with C news input subsystem.
- X * newsboot must be told to run partial batches left at a crash.
- X */
- X#include "../common/conf.h"
- X#include "common.h"
- X#include <signal.h>
- X
- X#define TOOBIG 300000L /* batch > TOOBIG bytes, kick rnews */
- X#define TOOOLD (5*60) /* batch > TOOOLD seconds old, kick rnews */
- X#define COPYSIZE 8192 /* bytes to copy at one time */
- X#define MAXDIGITS 25 /* lg(maxlongint) + epsilon */
- X#define MAXSTR 1024
- X
- X#define INDIR artfile("in.coming")
- X#define BATCHFILE artfile("in.coming/nntp.XXXXXX")
- X#define NEWSRUN binfile("input/newsrun")
- X
- X#define YES 1
- X#define NO 0
- X
- X/* imports */
- Xextern time_t time();
- Xextern char *malloc(), *mktemp(), *index(), *rindex();
- X
- X/* forwards */
- Xstatic char *artfile(), *binfile(), *strsave();
- Xstatic void error(), warning();
- Xstatic int xfer_timeout();
- X
- X/* private data */
- Xstatic char tempfile[256];
- Xstatic int xfer_lines, old_xfer_lines;
- X
- Xstatic char art[COPYSIZE]; /* entire article, if it fits */
- Xstatic char *endart = art; /* points just past end of article */
- Xstatic int incore = YES;
- X
- Xstatic struct batch_file {
- X char *name;
- X FILE *file;
- X char isopen;
- X time_t start; /* time of creation */
- X off_t size; /* current size */
- X} btch = { NULL, NULL, NO, 0, 0 };
- X
- Xchar *progname = "nntpd";
- X
- X#ifndef lint
- Xstatic char *sccsid = "@(#)batch.c 1.5 (Toronto) 31/4/89";
- X#endif
- X
- X/*
- X * stash stdin (up to ".") on the end of the batch input file.
- X * kick newsrun if the batch is non-empty and too big or too old.
- X *
- X * Parameters:
- X * "cont_code" is the response code to transmit on successful startup.
- X * "err_code" is the response code to transmit when something goes wrong.
- X *
- X * Returns: -1 on non-zero return from child, 0 on error before fork/exec, 1 else.
- X * Side effects: Creates and removes temporary file; accepts input from client.
- X * Can time out if XFER_TIMEOUT is defined.
- X */
- Xint
- Xbatch_input_article(cont_code, err_code, errbuf)
- Xint cont_code, err_code;
- Xchar *errbuf;
- X{
- X int status = 1; /* okay status */
- X
- X /* protect locking */
- X signal(SIGINT, SIG_IGN);
- X signal(SIGQUIT, SIG_IGN);
- X signal(SIGHUP, SIG_IGN);
- X
- X if (btch.name == NULL) {
- X /* BATCHFILE may trigger unprivileged() */
- X btch.name = mktemp(strsave(BATCHFILE));
- X }
- X if (btch.name == NULL)
- X return 0;
- X#ifdef notdef
- X (void) setgid(getegid());
- X (void) setuid(geteuid());
- X#endif
- X tempfile[0] = '\0';
- X if (!cpstdin(cont_code, err_code, errbuf)) /* may create tempfile */
- X return 0;
- X#ifdef POSTER
- X (void) chown(tempfile, uid_poster, gid_poster);
- X#endif
- X status = appbatch();
- X if (tempfile[0] != '\0')
- X (void) unlink(tempfile);
- X if (status == 1 && oktorunbatch())
- X status = enqueue(cont_code, err_code, errbuf);
- X return status;
- X}
- X
- Xint /* boolean */
- Xoktorunbatch()
- X{
- X struct stat stbuf;
- X
- X if (!btch.isopen || fstat(fileno(btch.file), &stbuf) < 0)
- X return NO;
- X btch.size = stbuf.st_size;
- X return btch.size > TOOBIG ||
- X btch.size > 0 && time((time_t *)NULL) - btch.start > TOOOLD;
- X}
- X
- X/*
- X * Copy standard input (up to a "." line) to art, if it fits,
- X * else to a temporary file.
- X */
- X/* ARGSUSED errbuf */
- Xstatic int /* boolean: got article ok? */
- Xcpstdin(cont_code, err_code, errbuf)
- Xint cont_code, err_code;
- Xchar *errbuf;
- X{
- X register FILE *tfp = NULL;
- X register char *cp, *realline;
- X char line[NNTP_STRLEN];
- X int toobig = NO;
- X int (*otimeout)();
- X
- X /* TODO: is this right? used to open here, with errors here */
- X printf("%d Ok\r\n", cont_code);
- X (void) fflush(stdout);
- X
- X xfer_lines = old_xfer_lines = 0;
- X incore = YES;
- X art[0] = '\0';
- X endart = art;
- X#ifdef XFER_TIMEOUT
- X otimeout = signal(SIGALRM, xfer_timeout);
- X (void) alarm(XFER_TIMEOUT);
- X#endif
- X while (fgets(line, sizeof line, stdin) != NULL) {
- X xfer_lines++;
- X if ((cp = rindex(line, '\r')) != NULL ||
- X (cp = rindex(line, '\n')) != NULL)
- X *cp = '\0'; /* nuke CRLF */
- X if (line[0] == '.' && line[1] == '\0')
- X break; /* article end: exit */
- X /* remove hidden dot if present */
- X realline = (line[0] == '.'? line+1: line);
- X if (toobig) { /* straight to disk */
- X (void) fputs(realline, tfp);
- X (void) putc('\n', tfp);
- X } else {
- X int len = strlen(realline);
- X
- X /*
- X * Does art have room to append realline + \n\0?
- X * If not, open temp file and dump art & realline there.
- X */
- X if (sizeof art - (endart - art) < len + 1 + 1) {
- X (void) strcpy(tempfile, "/tmp/rpostXXXXXX");
- X (void) mktemp(tempfile);
- X tfp = fopen(tempfile, "w");
- X if (tfp == NULL) {
- X printf("%d Cannot create temporary file.\r\n",
- X err_code);
- X (void) fflush(stdout);
- X return 0;
- X }
- X#ifdef OK_IN_MIDDLE_OKAY
- X else {
- X printf("%d Ok\r\n", cont_code);
- X (void) fflush(stdout);
- X }
- X#endif
- X (void) fwrite(art, 1, endart - art, tfp);
- X toobig = YES;
- X incore = NO;
- X art[0] = '\0';
- X endart = art;
- X (void) fputs(realline, tfp);
- X (void) putc('\n', tfp);
- X } else {
- X /* fits: append realline\n to art at endart */
- X (void) strcpy(endart, realline);
- X endart += len;
- X *endart++ = '\n';
- X *endart = '\0';
- X }
- X }
- X }
- X if (tfp != NULL)
- X (void) fclose(tfp);
- X#ifdef XFER_TIMEOUT
- X (void) alarm(0);
- X (void) signal(SIGALRM, otimeout);
- X#endif
- X
- X /* See if the connection got closed somehow... */
- X if (line[0] != '.' && line[1] != '\0') {
- X if (tempfile[0] != '\0')
- X (void) unlink(tempfile);
- X#ifdef LOG
- X syslog(LOG_ERR, "%s spawn: EOF before period on line by itself",
- X hostname);
- X#else
- X syslog(LOG_ERR, "spawn: EOF before period on line by itself");
- X#endif
- X return 0;
- X }
- X return 1;
- X}
- X
- Xstatic int
- Xxfer_timeout()
- X{
- X#ifdef XFER_TIMEOUT
- X if (old_xfer_lines < xfer_lines) {
- X old_xfer_lines = xfer_lines;
- X (void) alarm(XFER_TIMEOUT);
- X return;
- X }
- X /* Timed out. */
- X printf("%d timeout after %d seconds, closing connection.\r\n",
- X ERR_FAULT, XFER_TIMEOUT);
- X fflush(stdout);
- X#ifdef LOG
- X syslog(LOG_ERR, "%s transfer_timeout", hostname);
- X#endif LOG
- X (void) unlink(tempfile);
- X exit(1);
- X#endif XFER_TIMEOUT
- X}
- X
- X/*
- X * Append "#! rnews count" and art (or tempfile) to batch file, locking assumed.
- X * If batch file is too big or too old (but not empty), feed it to newsrun.
- X */
- Xstatic int /* same as batch_input_article */
- Xappbatch()
- X{
- X register FILE *tfp = NULL;
- X register int bytes = 0;
- X int status = 1; /* okay status */
- X long size = 0;
- X char artbuf[COPYSIZE];
- X struct stat stbuf;
- X
- X if (btch.file == NULL) {
- X btch.file = fopen(btch.name, "a");
- X if (btch.file == NULL)
- X return 0;
- X btch.isopen = YES;
- X btch.size = 0;
- X btch.start = time(&btch.start);
- X }
- X
- X /* find article size and write the article */
- X if (incore)
- X size = endart - art;
- X else {
- X tfp = fopen(tempfile, "r");
- X if (tfp == NULL)
- X return 0;
- X if (fstat(fileno(tfp), &stbuf) >= 0)
- X size = stbuf.st_size;
- X }
- X (void) fprintf(btch.file, "#! rnews %ld\n", size);
- X
- X /* copy the article to the batch file */
- X if (incore)
- X (void) fwrite(art, 1, endart - art, btch.file);
- X else {
- X while ((bytes = fread(artbuf, 1, sizeof artbuf, tfp)) > 0)
- X if (fwrite(artbuf, 1, bytes, btch.file) != bytes) {
- X warning("can't write %s", btch.name);
- X status = 0; /* hmm, #! count is off */
- X break;
- X }
- X (void) fclose(tfp);
- X }
- X if (fflush(btch.file) == EOF) {
- X warning("can't write %s", btch.name);
- X status = 0;
- X }
- X return status;
- X}
- X
- X/*
- X * Enqueue any partial batch. Called before exit.
- X */
- Xenqpartbatch(cont_code, err_code, errbuf)
- Xint cont_code, err_code;
- Xchar *errbuf;
- X{
- X struct stat stbuf;
- X
- X if (btch.isopen && fstat(fileno(btch.file), &stbuf) >= 0) {
- X if (btch.size > 0)
- X enqueue(cont_code, err_code, errbuf);
- X else {
- X (void) fclose(btch.file);
- X btch.file = NULL;
- X btch.isopen = NO;
- X (void) unlink(btch.name); /* remove empty batch */
- X }
- X }
- X}
- X
- X/*
- X * insert the batch file into the input subsystem queue by renaming
- X * it to an all-numeric name, then kick newsrun to process it.
- X * locks btch.name as appropriate.
- X */
- Xstatic int /* same as batch_input_article */
- Xenqueue(cont_code, err_code, errbuf)
- Xint cont_code, err_code;
- Xchar *errbuf;
- X{
- X time_t now;
- X int pid, wpid, status, fd, exitstat;
- X char permname[MAXDIGITS], *number = permname, *newsrun;
- X struct stat stbuf;
- X
- X (void) fclose(btch.file);
- X btch.file = NULL;
- X btch.isopen = NO;
- X btch.start = 0;
- X btch.size = 0;
- X
- X (void) fflush(stdout);
- X (void) fflush(stderr);
- X pid = fork();
- X if (pid == -1) {
- X warning("can't fork", "");
- X return 0;
- X } else if (pid != 0) { /* parent */
- X while ((wpid = wait(&status)) != -1 && wpid != pid)
- X ;
- X exitstat = (status>>8)&0377;
- X if (exitstat != 0) {
- X syslog(LOG_ERR, "%s: enqueue returned exit status 0%o",
- X progname, exitstat);
- X strcpy(errbuf, "enqueue failed to run newsrun\n");
- X }
- X return exitstat != 0? -1 :1;
- X }
- X
- X /* child: must exit */
- X for (fd = 3; fd < 20; fd++)
- X (void) close(fd);
- X if (chdir(INDIR) < 0) {
- X syslog(LOG_ERR, "%s: chdir(%s) failed", progname, INDIR);
- X nerror("can't change directory to %s", INDIR);
- X }
- X
- X /* rename btch.name to a number so newsrun will see it */
- X sprintf(number, "%ld", (long)time(&now));
- X while (link(btch.name, permname) < 0) {
- X if (stat(btch.name, &stbuf) < 0)
- X break;
- X sleep(2);
- X sprintf(number, "%ld", (long)time(&now));
- X }
- X if (unlink(btch.name) < 0)
- X vanished(btch.name);
- X
- X signal(SIGINT, SIG_IGN);
- X signal(SIGQUIT, SIG_IGN);
- X signal(SIGHUP, SIG_IGN);
- X (void) fflush(stdout);
- X (void) fflush(stderr);
- X newsrun = strsave(NEWSRUN);
- X if (newsrun == NULL)
- X newsrun = "/usr/lib/newsbin/input/newsrun";
- X execl(newsrun, newsrun, (char *)NULL);
- X syslog(LOG_ERR, "%s: can't run %s", progname, newsrun);
- X error("attempt to run %s failed!", newsrun);
- X exit(1);
- X /* NOTREACHED */
- X}
- X
- Xvanished(s) /* grieve for s, nerror [exit] */
- Xchar *s;
- X{
- X syslog(LOG_ERR, "%s: %s vanished underfoot!", progname, s);
- X nerror("%s vanished underfoot!", s); /* unlocks, exits */
- X}
- X
- Xstatic
- Xnerror(fmt, s) /* error, unused to be with unlock */
- Xchar *fmt, *s;
- X{
- X error(fmt, s);
- X}
- X
- X/* C news library starts here */
- X
- X/*
- X * error - print best error message possible and exit
- X */
- Xstatic void warning();
- X
- Xstatic void
- Xerror(s1, s2)
- Xchar *s1;
- Xchar *s2;
- X{
- X warning(s1, s2);
- X exit(1);
- X}
- X
- X/*
- X * warning - print best error message possible and clear errno
- X */
- Xextern int errno, sys_nerr;
- Xextern char *sys_errlist[];
- Xextern char *progname;
- Xextern char *getenv();
- X
- Xstatic void
- Xwarning(s1, s2)
- Xchar *s1;
- Xchar *s2;
- X{
- X char *cmdname;
- X
- X (void) fflush(stdout); /* hack */
- X cmdname = getenv("CMDNAME");
- X if (cmdname != NULL && *cmdname != '\0')
- X fprintf(stderr, "%s:", cmdname); /* No space after :. */
- X if (progname != NULL)
- X fprintf(stderr, "%s: ", progname);
- X fprintf(stderr, s1, s2);
- X if (errno > 0 && errno < sys_nerr)
- X fprintf(stderr, " (%s)", sys_errlist[errno]);
- X fprintf(stderr, "\n");
- X errno = 0;
- X}
- X
- Xvoid
- Xunprivileged()
- X{
- X (void) setgid(getgid());
- X (void) setuid(getuid());
- X}
- X
- Xstatic char *
- Xartfile(s)
- Xchar *s;
- X{
- X static char name[MAXSTR];
- X
- X strcpy(name, "/usr/spool/news/");
- X strcat(name, s);
- X return name;
- X}
- X
- Xstatic char *
- Xbinfile(s)
- Xchar *s;
- X{
- X static char name[MAXSTR];
- X
- X strcpy(name, "/usr/lib/newsbin/");
- X strcat(name, s);
- X return name;
- X}
- X
- X#ifdef notdef
- Xstatic char *
- Xctlfile(s)
- Xchar *s;
- X{
- X static char name[MAXSTR];
- X
- X strcpy(name, "/usr/lib/news/");
- X strcat(name, s);
- X return name;
- X}
- X#endif
- X
- Xstatic char *
- Xstrsave(s)
- Xregister char *s;
- X{
- X register char *news = malloc((unsigned)(strlen(s) + 1));
- X
- X if (news != NULL)
- X strcpy(news, s);
- X return news;
- X}
- X
- X#ifndef SYSLOG
- X/* VARARGS 2 */
- Xstatic
- Xsyslog(level, fmt)
- Xint level;
- Xchar *fmt;
- X{
- X}
- X#endif
- X
- !
- echo 'nntpdiffs/cdiff.1.5.0':
- sed 's/^X//' >'nntpdiffs/cdiff.1.5.0' <<'!'
- XCommon subdirectories: ../nntp.1.5.0/common and ./common
- XCommon subdirectories: ../nntp.1.5.0/doc and ./doc
- XCommon subdirectories: ../nntp.1.5.0/inews and ./inews
- XOnly in .: nntp.1.5.C.diff
- XCommon subdirectories: ../nntp.1.5.0/rrnpatches and ./rrnpatches
- XCommon subdirectories: ../nntp.1.5.0/server and ./server
- XCommon subdirectories: ../nntp.1.5.0/support and ./support
- XCommon subdirectories: ../nntp.1.5.0/xfer and ./xfer
- XCommon subdirectories: ../nntp.1.5.0/xmit and ./xmit
- Xdiff -r -c ../nntp.1.5.0/server/Makefile ./server/Makefile
- X*** ../nntp.1.5.0/server/Makefile Fri Feb 26 02:47:58 1988
- X--- ./server/Makefile Tue Jun 6 23:15:49 1989
- X***************
- X*** 3,8 ****
- X--- 3,9 ----
- X #
- X
- X SRVROBJ = main.o serve.o access.o access_inet.o access_dnet.o active.o \
- X+ batch.o \
- X ahbs.o globals.o group.o help.o ihave.o list.o misc.o netaux.o \
- X newgroups.o newnews.o nextlast.o ngmatch.o post.o parsit.o scandir.o \
- X slave.o spawn.o strcasecmp.o subnet.o time.o xhdr.o fakesyslog.o \
- X***************
- X*** 9,14 ****
- X--- 10,16 ----
- X ../common/version.o
- X
- X SRVRSRC = main.c serve.c access.c access_inet.c access_dnet.c active.c \
- X+ batch.c \
- X ahbs.c globals.c group.c help.c ihave.c list.c misc.c netaux.c \
- X newgroups.c newnews.c nextlast.c ngmatch.c post.c parsit.c scandir.c \
- X slave.c spawn.c strcasecmp.c subnet.c time.c xhdr.c fakesyslog.c \
- X***************
- X*** 19,25 ****
- X SRCS = ${SRVRSRC}
- X
- X # -ldbm here if you've #define'ed DBM in ../common/conf.h
- X! LIBS =
- X
- X CFLAGS = -O
- X
- X--- 21,27 ----
- X SRCS = ${SRVRSRC}
- X
- X # -ldbm here if you've #define'ed DBM in ../common/conf.h
- X! LIBS = -ldbm
- X
- X CFLAGS = -O
- X
- XOnly in ./server: batch.c
- Xdiff -r -c ../nntp.1.5.0/server/ihave.c ./server/ihave.c
- X*** ../nntp.1.5.0/server/ihave.c Tue Jan 12 02:53:11 1988
- X--- ./server/ihave.c Tue Jun 6 23:15:52 1989
- X***************
- X*** 43,49 ****
- X return;
- X }
- X
- X! retcode = spawn(rnews, "rnews", (char *) 0, CONT_XFER, ERR_XFERFAIL, errbuf);
- X if (retcode <= 0)
- X printf("%d %s\r\n", ERR_XFERFAIL, errbuf);
- X else if (retcode > 0)
- X--- 43,55 ----
- X return;
- X }
- X
- X! #ifdef UNBATCHED_INPUT
- X! retcode = spawn(rnews, "rnews", (char *) 0, CONT_XFER,
- X! ERR_XFERFAIL, errbuf);
- X! #else
- X! /* C news input hook */
- X! retcode = batch_input_article(CONT_XFER, ERR_XFERFAIL, errbuf);
- X! #endif
- X if (retcode <= 0)
- X printf("%d %s\r\n", ERR_XFERFAIL, errbuf);
- X else if (retcode > 0)
- Xdiff -r -c ../nntp.1.5.0/server/misc.c ./server/misc.c
- X*** ../nntp.1.5.0/server/misc.c Sun Feb 7 01:29:33 1988
- X--- ./server/misc.c Tue Jun 6 23:15:54 1989
- X***************
- X*** 82,88 ****
- X *
- X * Side effects: opens dbm database
- X * (only once, keeps it open after that).
- X- * Converts "msg_id" to lower case.
- X */
- X
- X #ifndef NDBM
- X--- 82,87 ----
- X***************
- X*** 115,124 ****
- X datum key, content;
- X #endif USGHIST
- X static FILE *hfp = NULL; /* history file, text version */
- X-
- X- for (cp = msg_id; *cp != '\0'; ++cp)
- X- if (isupper(*cp))
- X- *cp = tolower(*cp);
- X
- X #ifdef USGHIST
- X hfp = fopen(histfile(msg_id), "r");
- X--- 114,119 ----
- Xdiff -r -c ../nntp.1.5.0/server/newnews.c ./server/newnews.c
- X*** ../nntp.1.5.0/server/newnews.c Sat Feb 6 20:29:07 1988
- X--- ./server/newnews.c Tue Jun 6 23:15:57 1989
- X***************
- X*** 255,263 ****
- X * Side effects: Seeks in history file, modifies line.
- X */
- X
- X! seekuntil(fp, key, line, linesize)
- X FILE *fp;
- X! char *key;
- X char *line;
- X int linesize;
- X {
- X--- 255,263 ----
- X * Side effects: Seeks in history file, modifies line.
- X */
- X
- X! seekuntil(fp, akey, line, linesize)
- X FILE *fp;
- X! char *akey;
- X char *line;
- X int linesize;
- X {
- X***************
- X*** 264,270 ****
- X--- 264,273 ----
- X char datetime[32];
- X register int c;
- X register long top, bot, mid;
- X+ extern long dtol();
- X+ char key[30];
- X
- X+ (void) sprintf(key, "%ld", dtol(akey)); /* akey -> time_t in ascii */
- X bot = 0;
- X (void) fseek(fp, 0L, 2);
- X top = ftell(fp);
- X***************
- X*** 327,332 ****
- X--- 330,338 ----
- X }
- X
- X
- X+ /*
- X+ * C news version of getword.
- X+ */
- X getword(fp, w, line, linesize)
- X FILE *fp;
- X register char *w;
- X***************
- X*** 334,369 ****
- X int linesize;
- X {
- X register char *cp;
- X
- X if (fgets(line, linesize, fp) == NULL)
- X return (0);
- X! if (cp = index(line, '\t')) {
- X! /*
- X! * The following gross hack is present because the history file date
- X! * format is braindamaged. They like "mm/dd/yy hh:mm", which is useless
- X! * for relative comparisons of dates using something like atoi() or
- X! * strcmp. So, this changes their format into yymmddhhmm. Sigh.
- X! *
- X! * 12345678901234 ("x" for cp[x])
- X! * mm/dd/yy hh:mm (their lousy representation)
- X! * yymmddhhmm (our good one)
- X! * 0123456789 ("x" for w[x])
- X! */
- X! *cp = '\0';
- X! (void) strncpy(w, cp+1, 15);
- X! w[0] = cp[7]; /* Years */
- X! w[1] = cp[8];
- X! w[2] = cp[1]; /* Months */
- X! w[3] = cp[2];
- X! w[4] = cp[4]; /* Days */
- X! w[5] = cp[5];
- X! w[6] = cp[10]; /* Hours */
- X! w[7] = cp[11];
- X! w[8] = cp[13]; /* Minutes */
- X! w[9] = cp[14];
- X! w[10] = '\0';
- X! } else
- X! w[0] = '\0';
- X return (1);
- X }
- X
- X--- 340,362 ----
- X int linesize;
- X {
- X register char *cp;
- X+ extern char *index();
- X
- X if (fgets(line, linesize, fp) == NULL)
- X return (0);
- X! w[0] = '\0'; /* in case of bad format */
- X! if (cp = index(line, '\t')) { /* find 2nd field */
- X! register char *endp;
- X!
- X! *cp++ = '\0';
- X! endp = index(cp, '~'); /* end of date-received */
- X! if (endp == NULL)
- X! endp = index(cp, '\t'); /* end of expiry */
- X! if (endp != NULL) {
- X! (void) strncpy(w, cp, endp - cp);
- X! w[endp - cp] = '\0';
- X! }
- X! }
- X return (1);
- X }
- X
- Xdiff -r -c ../nntp.1.5.0/server/serve.c ./server/serve.c
- X*** ../nntp.1.5.0/server/serve.c Thu Feb 25 22:49:21 1988
- X--- ./server/serve.c Tue Jun 6 23:16:00 1989
- X***************
- X*** 237,244 ****
- X--- 237,251 ----
- X
- X printf("%d %s closing connection. Goodbye.\r\n", OK_GOODBYE, host);
- X (void) fflush(stdout);
- X+ #ifndef UNBATCHED_INPUT
- X+ {
- X+ char errbuf[2 * NNTP_STRLEN];
- X
- X+ enqpartbatch(CONT_XFER, ERR_XFERFAIL, errbuf);
- X+ }
- X+ #endif
- X
- X+
- X #ifdef LOG
- X if (ferror(stdout))
- X syslog(LOG_ERR, "%s disconnect: %m", hostname);
- X***************
- X*** 287,293 ****
- X #ifdef PROFILE
- X profile();
- X #endif
- X-
- X exit(0);
- X }
- X
- X--- 294,299 ----
- !
- echo done
-
-
-